<template>
    <div id="VJForm">
        <el-form :validate-on-rule-change="false" v-loading="loading" :inline="inline" :model="formData" :rules="inline?{}:rules" v-bind="combineCfg"
                 ref="formEl">
            <template v-for="({config,type,name,cmp,label,show,underSuffix,inline},key) in cfgList">
                <slot name="form-section-title" v-if="titleSlotIdxs&&titleSlotIdxs.includes(key)" :idx="key"/>
                <el-form-item :prop="name" :label="label" v-show="_checkVisible(show)">
                    <!--  inline form item -->
                    <ol v-if="inline" class="l-inline">
                        <li v-if="inline[0]">{{inline[0]}}</li>
                        <li>
                            <component v-on="$listeners" :prop-name="name" :is="type" :config="config" :cmp="cmp"
                                       :value="modelData[name]" @input="updateModelData(name,$event)"/>
                        </li>
                        <li v-if="inline[1]">{{inline[1]}}</li>
                    </ol>
                    <template v-else-if="type">
                        <component v-on="$listeners" :prop-name="name" :is="type" :config="config" :cmp="cmp"
                                   :value="modelData[name]" @input="updateModelData(name,$event)"/>
                    </template>
                    <span v-else>{{modelData[name]}}</span>
                    <p class="under-suffix" v-if="underSuffix">注释：{{underSuffix}}</p>
                </el-form-item>
                <slot name="form-item" v-if="key===+slotIdx-1"/>
                <slot name="form-items" v-if="slotIdxList&&slotIdxList.includes(key)" :idx="key"/>
            </template>
            <el-form-item v-if="!hideFoot">
                <el-button type="primary" style="width: 160px;" @click="preSubmit">{{submitText||"提交"}}</el-button>
                <el-button v-if="!hideReset" @click="$emit('reset'),modelData=cacheData">重置</el-button>
                <el-button   v-if="$listeners.close" @click="$emit('close')">关闭</el-button>
            </el-form-item>
        </el-form>
    </div>
</template>
<script>
    import VjInput from "./vj-input.vue";
    import {
        createFormData,
        createFormRule,
        formatFormData,
        cloneDeep,
        ruleFormValid,
        checkVisible
    } from "vijay-util";
    import VjNumber from "./vj-number.vue";
    import VjDate from "./vj-date.vue";
    import VjSelect from "./vj-select.vue";
    import VjUpload from "./vj-upload.vue";
    import VjRadioCmp from "./vj-radio-cmp.vue";
    import VjFile from "./vj-file.vue";
    import VjAddr from "./vj-addr.vue";
    import {DefaultFormStyle} from "./config/form";

    export default {
        name: "vjForm",
        props: {
            cfgList: {type: Array, required: true},
            formData: {type: Object, required: true},
            hideFoot: {type: Boolean, default: false},
            inline: Boolean,
            loading: Boolean,
            isNew: Boolean,
            hideReset: Boolean,
            styleConfig: Object,
            submitText: String,
            slotIdx: String | Number,
            titleSlotIdxs: Array,
            slotIdxList: Array,
            action: String
        },
        components: {
            VjRadioCmp, VjUpload, VjSelect, VjDate, VjNumber, VjInput,VjFile,VjAddr
        },
        data() {
            return {cacheData: {}, rules: {}}
        },
        methods: {
            validForm() {
                return ruleFormValid(this.$refs.formEl)
            },
            _checkVisible() {
                return checkVisible(this.formData, ...arguments)
            },
            updateModelData(key, val) {
                this.modelData = {...this.modelData, [key]: val};
            },
            async preSubmit() {
                const el = this.$refs.formEl;
                await ruleFormValid(el);
                this.$emit("submit")
            },
            setupCacheData() {
                if (this.isNew) return this.$off("formatFormData")
                //如果至少有2条数据是有值的 就认为是回显的data
                //可以改为 调用函数替换formData 当触发initData时 触发一个事件 该组件监听事件进行触发回显 避免默认值的问题
                if (Object.values(this.formData).filter(Boolean).length < 2 ) return;
                this.modelData = this.modelData
                this.cacheData = cloneDeep(this.modelData);
                this.$off("formatFormData")
            }
        },
        computed: {
            combineCfg() {
                return Object.assign({labelWidth: this.hideFoot ? 'auto' : "120px"}, DefaultFormStyle, this.styleConfig)
            },
            modelData: {
                deep: true,
                get() {
                    return createFormData(this.cfgList, this.formData)
                },
                set(val) {
                    this.$emit("update:formData", formatFormData(this.cfgList, val))
                }
            }
        },
        watch: {
            formData(val) {
                this.$emit("formatFormData");
                this.rules = createFormRule(this.formData, this.cfgList)
            }
        },
        created() {
            if (this.isNew) this.cacheData = createFormData(this.cfgList, this.formData)
            this.rules = createFormRule(this.formData, this.cfgList);
            this.$on("formatFormData", () => this.setupCacheData())
        }
    }
</script>

<style scoped lang="scss">
    #VJForm{
        /deep/ .el-form-item__label-wrap{
            margin-left:0 !important;
        }
        .under-suffix{
            color:#8c939d;
            font-size:14px;
            line-height:1.2;
            margin-top:14px;
        }
        .l-inline{
            display:flex;
            align-items:center;
            color:#8c939d;
            & > li:not(:last-child){
                margin-right:10px;
            }
        }
    }
</style>
